package com.users.rn.rncommon.plugin;

import com.users.rn.common.download.impl.ZipUtils;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.bridge.CatalystInstance;
import com.facebook.react.bridge.CatalystInstanceImpl;
import com.facebook.react.bridge.JSBundleLoader;
import com.facebook.react.bridge.ReactContext;
import com.users.rn.rncommon.manager.ALHReactNativeHost;
import com.users.rn.rncommon.model.PluginInfo;
import com.users.rn.rncommon.util.ReactConst;
import com.users.rn.rncommon.util.ReactUtils;

/**
 * @Description:
 * @Author: bluce
 * @Date: 2020/12/3 13:50
 */
public final class ReactLoadUtils {
    public interface OnLoadScriptListener {
        /**
         * 加载bundle回调
         * @param responseStatus 0 success, other fail
         * @param msg
         */
        void onResponse(int responseStatus, String msg);
    }

    /**
     * 加载bundle（拆包加载还是未拆包加载在这里做统一处理）
     * @param host
     * @param listener
     */
    public static void loadBundle(ALHReactNativeHost host, OnLoadScriptListener listener, PluginInfo info){
        if(host != null && info != null){
            if(info.isUnpacking()){
                //拆包加载，判断需要加载的moduleId是否被加载过
                boolean hasLoadedModuleId = host.isHasLoadedModuleId(info.getModuleId());
                if(hasLoadedModuleId){
                    if(listener != null){
                        listener.onResponse(ReactConst.LOAD_BUNDLE_SUCCESS , "loadBundleForUnPacking success");
                    }
                }else{
                    loadBundleScript(host, listener, info);
                }
            }else{
                //未拆包加载
                ReactInstanceManager reactInstanceManager = host.getReactInstanceManager();
                if (reactInstanceManager == null) {
                    if (listener != null) {
                        listener.onResponse(ReactConst.LOAD_BUNDLE_FAILED, "loadBundleScript ReactInstanceManager is null");
//                        Log.log2File("ReactLoadUtils loadBundleScript ReactInstanceManager is null,pluginId="+info.getPluginId());
                    }
                    return;
                }
                ReactContext currentReactContext = reactInstanceManager.getCurrentReactContext();
                if (currentReactContext == null) {
                    if (listener != null) {
                        listener.onResponse(ReactConst.LOAD_BUNDLE_FAILED_BY_CONTEXT_NOT_READY, "loadBundleScript ReactContext is null");
//                        Log.log2File("ReactLoadUtils loadBundleScript ReactContext is nulll,pluginId="+info.getPluginId());
                    }
                    return;
                }
                if(listener != null){
                    listener.onResponse(ReactConst.LOAD_BUNDLE_SUCCESS , "loadBundleForPacking success");
                }
            }
        }else{
            if(listener != null){
                listener.onResponse(ReactConst.LOAD_BUNDLE_FAILED , "loadBundle plugModuleInfo = null or host = null");
//                Log.log2File("ReactLoadUtils loadBundle plugModuleInfo = null or host = null,pluginId="+info.getPluginId());
            }
        }
    }

    /**
     * 加载拆包bundle，仅内部调用
     *
     * @param host
     * @param l
     */
    private static void loadBundleScript(ALHReactNativeHost host, OnLoadScriptListener l, PluginInfo info) {
        if (host == null) {
            if (l != null) {
                l.onResponse(ReactConst.LOAD_BUNDLE_FAILED, "loadBundleScript ReactNativeHost is null");
                if (info != null){
//                    Log.log2File("ReactLoadUtils loadBundleScript ReactNativeHost is null,pluginId="+info.getPluginId());
                }
            }
            return;
        }
        if (info == null) {
            if (l != null) {
                l.onResponse(ReactConst.LOAD_BUNDLE_FAILED, "loadBundleScript PlugModuleInfo is null");
                if (info != null){
//                    Log.log2File("ReactLoadUtils loadBundleScript PlugModuleInfo is null,pluginId="+info.getPluginId());
                }
            }
            return;
        }
        ReactInstanceManager reactInstanceManager = host.getReactInstanceManager();
        if (reactInstanceManager == null) {
            if (l != null) {
                l.onResponse(ReactConst.LOAD_BUNDLE_FAILED, "loadBundleScript ReactInstanceManager is null");
                if (info != null){
//                    Log.log2File("ReactLoadUtils loadBundleScript ReactInstanceManager is null,pluginId="+info.getPluginId());
                }
            }
            return;
        }
        ReactContext currentReactContext = reactInstanceManager.getCurrentReactContext();
        if (currentReactContext == null) {
            if (l != null) {
                l.onResponse(ReactConst.LOAD_BUNDLE_FAILED_BY_CONTEXT_NOT_READY, "loadBundleScript ReactContext is null");
                if (info != null){
//                    Log.log2File("ReactLoadUtils loadBundleScript ReactContext is null,pluginId="+info.getPluginId());
                }
            }
            return;
        }
        CatalystInstance ca = currentReactContext.getCatalystInstance();
        if (ca == null) {
            if (l != null) {
                l.onResponse(ReactConst.LOAD_BUNDLE_FAILED, "loadBundleScript CatalystInstance is null");
                if (info != null){
//                    Log.log2File("ReactLoadUtils loadBundleScript CatalystInstance is null,pluginId="+info.getPluginId());
                }
            }
            return;
        }
        try {
            CatalystInstanceImpl caImpl = (CatalystInstanceImpl) ca;
            String bundlePath = info.getBundlePath();
            //开关关 - 走本地
            if (!info.isEventFlag()) {
                //check file is existed
                boolean isFileExisted = ReactUtils.checkAssetsFileExist(currentReactContext, bundlePath);
                if(isFileExisted){
                    JSBundleLoader assetLoader = JSBundleLoader.createAssetLoader(currentReactContext, bundlePath, false);
                    assetLoader.loadScript(caImpl);
                    host.putModuleId(info.getModuleId());
                    if (l != null) {
                        l.onResponse(ReactConst.LOAD_BUNDLE_SUCCESS, "assetLoader success, bundle file path is " + bundlePath);
                    }
                }else{
                    if (l != null) {
                        l.onResponse(ReactConst.LOAD_ASSETS_BIZ_BUNDLE_FAILED, "assetLoader failed, bundle file path is " + bundlePath);
                        if (info != null){
//                            Log.log2File("ReactLoadUtils loadBundleScript assetLoader failed, bundle file path is,pluginId="+info.getPluginId()+
//                                    ",bundle file path is "+bundlePath);
                        }
                    }
                }
            }else{
                boolean isFileExisted = ReactUtils.checkSDCardFileExist(bundlePath);
                if(isFileExisted){
                    //先走sdcard
                    JSBundleLoader fileLoader = JSBundleLoader.createFileLoader(bundlePath);
                    fileLoader.loadScript(caImpl);
                    host.putModuleId(info.getModuleId());
                    if (l != null) {
                        l.onResponse(ReactConst.LOAD_BUNDLE_SUCCESS, "fileLoader success, bundle file path is " + bundlePath);
                    }
                }else{
                    //再走本地
                    boolean isExisted = ReactUtils.checkAssetsFileExist(currentReactContext, bundlePath);
                    if(isExisted){
                        JSBundleLoader assetLoader = JSBundleLoader.createAssetLoader(currentReactContext, bundlePath, false);
                        assetLoader.loadScript(caImpl);
                        host.putModuleId(info.getModuleId());
                        /**
                         * 当加载的bundle是本地 bundle时，需要进行以下判断：
                         *  判断当前pluginid是否存在sdcard下面的zip包文件，如果存在，加上此时sdcard bundle不存在，那么需要重新解压一次；否则不存在不作处理。
                         */
                        if (ZipUtils.INSTANCE.unzipBundle(currentReactContext, info.getPluginId())) {
                            ReactUtils.eventBizBundle(currentReactContext, info, "can not find sd card biz bundle");
                        }
                        if (l != null) {
                            l.onResponse(ReactConst.LOAD_BUNDLE_SUCCESS, "assetLoader success, bundle file path is " + bundlePath);
                        }
                    }else{
                        if (l != null) {
                            l.onResponse(ReactConst.LOAD_ASSETS_BIZ_BUNDLE_FAILED, "assetLoader failed, bundle file path is " + bundlePath);
                            if (info != null){
//                                Log.log2File("ReactLoadUtils loadBundleScript assetLoader failed2, bundle file path is,pluginId="+info.getPluginId()+
//                                        ",bundle file path is "+bundlePath);
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            if (l != null) {
                l.onResponse(ReactConst.LOAD_BUNDLE_FAILED, e.toString());
                if (info != null){
//                    Log.log2File("ReactLoadUtils loadBundleScript exception-"+e.getCause()+info.getPluginId());
                }
            }
            //异常打点
            ReactUtils.eventBizBundle(currentReactContext, info, e.toString());
        }
    }
}
